package com.ewing.busi.api.pay.service;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.ewing.busi.api.pay.constants.PayWay;
import com.ewing.busi.api.pay.dto.JsApiPayParam;
import com.ewing.busi.order.constants.OrderStatus;
import com.ewing.busi.order.dao.OrderDetailDao;
import com.ewing.busi.order.dao.OrderInfoDao;
import com.ewing.busi.order.model.OrderDetail;
import com.ewing.busi.order.model.OrderInfo;
import com.ewing.busi.pay.constants.BusiType;
import com.ewing.busi.pay.constants.PayStatus;
import com.ewing.busi.pay.dao.PayHistoryDao;
import com.ewing.busi.pay.dao.PayWxPrepayidDetailDao;
import com.ewing.busi.pay.model.PayHistory;
import com.ewing.busi.pay.model.PayWxPrepayidDetail;
import com.ewing.busi.web.mgr.WebResourceMgr;
import com.ewing.common.constants.AjaxRespCode;
import com.ewing.common.constants.IsEff;
import com.ewing.common.exception.BusinessException;
import com.ewing.core.auth.HttpSessionUtils;
import com.ewing.core.jdbc.BaseDao;
import com.ewing.core.wxpaysdk.api.WxpayApi;
import com.ewing.core.wxpaysdk.api.WxpayApiImpl;
import com.ewing.core.wxpaysdk.api.unifiedorders.vo.UnifiedOrdersResDto;
import com.ewing.core.wxpaysdk.constants.ReturnCode;
import com.ewing.utils.IntegerUtils;
import com.ewing.utils.JsonUtils;

@Repository("wxPayService")
public class WxPayService {

  /**
   * 默认生成的该类的LOG记录器，使用slf4j组件。避免产生编译警告，使用protected修饰符。
   */
  protected final static Logger logger = LoggerFactory.getLogger(WxPayService.class);


  @Resource
  private WebResourceMgr webResourceMgr;
  @Resource
  private BaseDao baseDao;
  @Resource
  private OrderDetailDao orderDetailDao;
  @Resource
  private PayHistoryDao payHistoryDao;
  @Resource
  private OrderInfoDao orderInfoDao;
  @Resource
  private PayWxPrepayidDetailDao payWxHistoryDetailDao;

  private WxpayApi payApi = new WxpayApiImpl();

  public JsApiPayParam pay(Integer cusId, Integer orderId, String ip)
      throws NumberFormatException, Exception {
    if (IntegerUtils.nullOrZero(cusId) || IntegerUtils.nullOrZero(orderId)) {
      return null;
    }

    return getPrepayId(cusId, orderId, ip);
  }

  /**
   * 微信支付-统一下单<br/>
   * 获取预付单，获取prepay_id
   * 
   * @param orderId
   * @return
   * @author Joeson
   * @throws Exception
   * @throws NumberFormatException
   */
  private JsApiPayParam getPrepayId(Integer cusId, Integer orderId, String ip)
      throws NumberFormatException, Exception {
    if (IntegerUtils.nullOrZero(orderId)) {
      return null;
    }

    OrderInfo orderInfo = orderInfoDao.findByIdAndCusId(orderId, cusId);
    if (!ObjectUtils.equals(orderInfo.getStatus(), OrderStatus.WAIT_PAY.getValue())) {
      throw new BusinessException(AjaxRespCode.ORDER_UN_NEED_PAY.code, "当前订单不需要支付");
    }
    List<OrderDetail> detailList = orderDetailDao.findByCusIdAndOrderId(orderId, cusId);
    return getPrePayId(orderInfo, detailList, ip);
  }

  private JsApiPayParam getPrePayId(OrderInfo orderInfo, List<OrderDetail> detailList, String ip)
      throws NumberFormatException, Exception {
    if (null == orderInfo || CollectionUtils.isEmpty(detailList)) {
      return null;
    }

    StringBuilder orderDetail = new StringBuilder();
    for (OrderDetail detail : detailList) {
      orderDetail
          .append(webResourceMgr.getResourceDetail(detail.getResourceId(), detail.getPriceId()));
    }

    logger.info("pre send");
    String orderDetailStr = orderDetail.length() > 0
        ? orderDetail.substring(0, orderDetail.length() - 1) : StringUtils.EMPTY;
    // 调用微信统一下单接口，获取预付单信息
    UnifiedOrdersResDto resDto = payApi.unifiedOrders(orderDetailStr, orderDetailStr,
        orderInfo.getBizId(), (int) Double.parseDouble("" + (orderInfo.getTotalPrice() * 100)), ip,
        orderInfo.getCreateTime(), StringUtils.EMPTY, orderInfo.getId(),
        HttpSessionUtils.getMarkId());
    logger.info("after send");
    logger.info(JsonUtils.toJson(resDto));

    if (null != resDto && StringUtils.isNotEmpty(resDto.getPrepayId())) {
      PayHistory payHistory =
          payHistoryDao.getByBusiIdAndBusiType(orderInfo.getId(), BusiType.ORDER);
      if (null == payHistory) {
        payHistory = new PayHistory();
      }
      payHistory.setBizId(orderInfo.getBizId());
      payHistory.setBusiType(BusiType.ORDER.getValue());
      payHistory.setBusiId(orderInfo.getId());
      payHistory.setPayWay(PayWay.WCPAY.getValue());
      payHistory.setCustomerId(orderInfo.getCustomerId());
      payHistory.setUserId(orderInfo.getUserId());
      payHistory.setPayFee(orderInfo.getTotalPrice());
      payHistory.setStatus(PayStatus.APPLY.getValue());
      payHistory.setPrePayId(resDto.getPrepayId());
      payHistory.setReturnCode(resDto.getResultCode());
      payHistory.setReturnMsg(resDto.getReturnMsg());
      payHistory.setCreateTime(new Date());
      baseDao.saveOrUpdate(payHistory);

      List<PayWxPrepayidDetail> payDetailList =
          payWxHistoryDetailDao.getByBizId(orderInfo.getBizId());
      if (CollectionUtils.isNotEmpty(payDetailList)) {
        for (PayWxPrepayidDetail payDetail : payDetailList) {
          payDetail.setIseff(IsEff.INEFFECTIVE.getValue());
        }
        baseDao.updateMuti(payDetailList);
      }

      // 保存微信支付信息详情
      PayWxPrepayidDetail historyDetail = new PayWxPrepayidDetail();
      historyDetail.setBizId(orderInfo.getBizId());
      historyDetail.setPrePayId(resDto.getPrepayId());
      historyDetail.setReturnCode(resDto.getResultCode());
      historyDetail.setReturnMsg(resDto.getReturnMsg());
      historyDetail.setIseff(IsEff.EFFECTIVE.getValue());
      historyDetail.setReturnDetail(JsonUtils.toJson(resDto));
      historyDetail.setStatus(ObjectUtils.equals(resDto.getResultCode(), ReturnCode.SUCCESS.name())
          ? PayStatus.SUCCESS.getValue() : PayStatus.FAIL.getValue());
      logger.info(JsonUtils.toJson(historyDetail));
      baseDao.save(historyDetail);

      return new JsApiPayParam(resDto.getPrepayId());
    }

    return null;
  }

}
